package ru.stepanovdn.trading.loader

import jakarta.persistence.Persistence
import jakarta.persistence.TypedQuery
import ru.stepanovdn.trading.loader.entity.Candle
import ru.stepanovdn.trading.loader.entity.Share
import ru.tinkoff.piapi.core.InvestApi
import java.time.Instant
import java.time.LocalDate
import java.time.ZoneId

fun daysInMonth(year:Int, month: Int) : Int {
    if ((month == 1) or (month == 3) or (month == 5) or (month == 7)
        or (month == 8) or (month == 10) or (month == 12)) {
        return 31
    } else if ((month == 4) or (month == 6) or (month == 9) or (month == 11)) {
        return 30
    } else {
        if (year % 4 == 0) {
            return 29
        } else {
            return 28
        }
    }
}

fun main() {
    Class.forName("org.postgresql.Driver");

    var token = System.getenv("token")
    var api = InvestApi.create(token);

    val entityManagerFactory = Persistence.createEntityManagerFactory("default")
    val em = entityManagerFactory.createEntityManager()
    em.transaction.begin()
    val query: TypedQuery<Share> = em.createQuery("from Share", Share::class.java)
    val shares: List<Share> = query.resultList
    em.transaction.commit()

    val years = listOf(2024)

    val timelineStartDate = LocalDate.of(2020, 4, 12)
    var timeline = timelineStartDate.atStartOfDay(ZoneId.of("UTC")).toInstant()

    for (s in shares) {
        if ("NVTK" != s.ticker) {
            continue
        }

        val figi = s.figi
        print(s.ticker+"\n")
        for (year in years) {
            print("year: $year \n")
            for (month in 1..12) {
                if (month < 6) {
                    continue
                }
                print("month: $month \n")
                val daysInMonth = daysInMonth(year, month)
                for (day in 1..daysInMonth) {
                    if (day < 25) {
                        continue
                    }
                    val startDate = LocalDate.of(year, month, day)
                    if (startDate.isBefore(LocalDate.now()) or startDate.equals(LocalDate.now())) {
                        print("date: $startDate \n")
                        var endDate: LocalDate
                        if (day < daysInMonth) {
                            endDate = LocalDate.of(year, month, day + 1)
                        } else {
                            if (month < 12) {
                                endDate = LocalDate.of(year, month + 1, 1)
                            } else {
                                endDate = LocalDate.of(year + 1, 1, 1)
                            }
                        }
                        val startDateInstant = startDate.atStartOfDay(ZoneId.of("UTC")).toInstant()
                        val endDateInstant = endDate.atStartOfDay(ZoneId.of("UTC")).toInstant()
                        val resp = api.marketDataService.getCandles(
                            figi,
                            startDateInstant,
                            endDateInstant,
                            ru.tinkoff.piapi.contract.v1.CandleInterval.CANDLE_INTERVAL_HOUR
                        )
                        val historicCandles = resp.get()
                        print("candles found ${historicCandles.size} \n")
                        em.transaction.begin()
                        for (hc in historicCandles) {
                            timeline = timeline.plusNanos(3600000000000)
                            val candle = Candle(
                                isin = s.isin,
                                ticker = s.ticker,
                                open = hc.open.units + hc.open.nano.toFloat() / Constants.NANO_DIVIDER,
                                high = hc.high.units + hc.high.nano.toFloat() / Constants.NANO_DIVIDER,
                                low = hc.low.units + hc.low.units.toFloat() / Constants.NANO_DIVIDER,
                                close = hc.close.units + hc.close.units.toFloat() / Constants.NANO_DIVIDER,
                                volume = hc.volume.toInt(),
                                time = Instant
                                    .ofEpochSecond(hc.time.seconds, hc.time.nanos.toLong())
                                    .atZone(ZoneId.of("UTC"))
                                    .toLocalDateTime(),
                                timeline = timeline.atZone(ZoneId.of("UTC")).toLocalDateTime(),
                                complete = hc.isComplete
                            )
                            Thread.sleep(300)
                            em.persist(candle)
                        }
                        em.transaction.commit()
                    }
                }
            }
        }
    }

    em.close()
    entityManagerFactory.close()
}